#
#      Copyright 2011 Miranda, Tom
#       
#       Licensed under the Apache License, Version 2.0 (the "License");
#       you may not use this file except in compliance with the License.
#       You may obtain a copy of the License at
#
#          http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing, software
#       distributed under the License is distributed on an "AS IS" BASIS,
#       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#       See the License for the specific language governing permissions and
#       limitations under the License.
#

import mc, threading, time, sage, livetv
from threading import RLock
from time import sleep

def areNewConflicts(oldConflicts, newConflicts):
	oldAirings = conflictsToDict(oldConflicts)
	newAirings = conflictsToDict(newConflicts)
	try:
		for k in newAirings.iterkeys():
			if k not in oldAirings:
				return True
		return False
	except:
		return False

# Converts a list of airing JSON object to a dictionary whose keys are the AiringIDs.
def conflictsToDict(conflicts):
	d = {}
	try:
		for conflict in conflicts:
			try:
				airingID = conflict['AiringID']
				d[airingID] = 'True'
			except:
				mc.LogDebug("sageBoxee: Found conflict with no AiringID.")
	except:
		pass
	return d
	
# Thread that runs in the background, looking for new unresolved conflicts.  If one is detected it displays a 
# pop-up dialog informing the user.	
class ConflictDetectionThread(threading.Thread):
	_status = None
	_keepAlive = True
	_api = None
	_lock = None

	def __init__(self, api):
		threading.Thread.__init__(self)
		self._api = api
		self._lock = RLock()

	def run(self):
		mc.LogDebug('SageBoxee: Conflict detection thread started.')
		self._status = None
			
		while 1:
			try:
				self._lock.acquire()

				# Get the airings that won't be recorded.
				expr = 'GetAiringsThatWontBeRecorded(true)'
				currentConflicts = self._api.EvaluateExpression(expr)

				# See if any conflicts exist now that didn't exist before.
				if areNewConflicts(self._status, currentConflicts):
					mc.LogDebug("SageBoxee: Found a new conflict.")
					updater = sage.getRunningThread('SageBoxeeIconStatus')
					if updater != None:
						mc.LogDebug("SageBoxee: StatusUpdater is running.")
						if updater.getActiveWindow() != 0 and not livetv.isPlayerActive():
							mc.ActivateWindow(14090)
						else:
							mc.LogDebug("SageBoxee: Not displaying conflict " + str(updater.getActiveWindow()) + ":" + str(livetv.isPlayerActive()))
					
				# Make the new conflicts the old conflicts.
				self._status = currentConflicts
				
				# Terminate if the signal was sent.
				if(not self._keepAlive):
					break
			finally:
				self._lock.release()
			sleep(30)
		mc.LogDebug('SageBoxee: Conflict detection thread has terminated!')

	def getStatus(self, id = None):
		self._lock.acquire()
		if(id == None):
			rc = self._status.copy()
		else:
			rc = self._status[id]
		self._lock.release()
		return rc

	def setKeepAlive(self, val):
		self._lock.acquire()
		self._keepAlive = val
		self._lock.release()
		
def stopConflictDetectionThread(t):
	t.setKeepAlive(False)
